<template>
  <div class="corp-config-page">
   <main>
     <div class="content">
       <div class="config-container">
         <div class="title-content">
           <span class="text">配置中心</span>
           <div class="btns">
<!--             <i class="el-icon-plus" @click="handleAdd"></i>-->
<!--             <i class="el-icon-edit-outline" @click="handleEdit"></i>-->
<!--             <i class="el-icon-delete" @click="handleDelete"></i>-->
           </div>
         </div>
         <div class="select-container">
           <span>选择项目</span>
           <el-select v-model="projectId" placeholder="请选择项目">
             <el-option
               v-for="(item, index) in projectList"
               :value="item.project_id"
               :label="item.project_name"
               :key="index"
               :title="item.project_name"
             >
             </el-option>
           </el-select>
         </div>
         <ul class="role-list">
           <li
             v-for="item in configList"
             :key="item.role_id"
             :title="item.role_name"
             :class="['role-item', activeRoleId === item.role_id ? 'active' : '']"
             @click="handleSelect(item)">
             <span>{{ item.role_name }}</span>
           </li>
         </ul>
       </div>
       <div class="table-container">
         <div class="btn-container">
           <el-button
             class="success"
             type="primary"
             :loading="btnLoading"
             @click="handleSave">
             保存修改
           </el-button>
         </div>
         <div class="config-content">
           <transition name="module-fade">
             <el-table
               v-show="hasShowModule"
               v-loading="tableLoading"
               :data="tableData"
               row-key="uuid"
               :max-height="$setRem(800)"
               :tree-props="{children: 'children', hasChildren: 'hasChildren'}">
               <el-table-column
                 prop="name"
                 label="模块名称"
                 :width="$setRem(400)">
               </el-table-column>
               <el-table-column label="功能">
                 <template slot-scope="scope">
                   <el-checkbox
                     v-if="scope.row.deep === 0"
                     :indeterminate="setIndeterminate(scope.row)"
                     :value="scope.row.checked"
                     @change="(val) => handleChange(val, scope.row)">
                     配置
                   </el-checkbox>
                   <el-checkbox
                     v-else
                     :value="scope.row.checked"
                     @change="(val) => handleChange(val, scope.row)">
                     配置
                   </el-checkbox>
                 </template>
               </el-table-column>
             </el-table>
           </transition>
           <transition name="module-fade">
             <div v-show="!hasShowModule" class="data-source-container">
               <ul class="data-source-list" v-if="dataSourceList.length">
                 <li
                   class="data-source-item"
                   v-for="item in dataSourceList"
                   :key="item.uuid">
                   <h3>{{ item.data_source_name }}</h3>
                   <div class="pattern">
                     <label>接口模式：</label>
                     <el-select
                       placeholder="请选择"
                       :value="setValue('interface_type', item)"
                       @change="(val) => handleDataChange(item, 'interface_type', val)">
                       <el-option
                         v-for="(item, index) in item.menuList"
                         :value="item"
                         :label="item"
                         :key="index"
                         :title="item"
                       >
                       </el-option>
                     </el-select>
                   </div>
                   <div class="data-content">
                     <template v-if="item.data_source_name === '三维模型'">
                       <label>账号：</label>
                       <el-input
                         class="user"
                         placeholder="账号"
                         :value="setValue('url', item)"
                         @input="(val) => handleDataChange(item, 'url', val)">
                       </el-input>
                       <label class="password">密码：</label>
                       <el-input
                         class="user"
                         placeholder="密码"
                         type="password"
                         show-password
                         :value="setValue('port', item)"
                         @input="(val) => handleDataChange(item, 'port', val)">
                       </el-input>
                     </template>
                     <template v-else>
                       <label>接口地址：</label>
                       <el-input
                         class="protocol"
                         placeholder="地址"
                         :value="setValue('url', item)"
                         @input="(val) => handleDataChange(item, 'url', val)">
                       </el-input>:
                       <el-input
                         class="port"
                         placeholder="端口"
                         :value="setValue('port', item)"
                         @input="(val) => handleDataChange(item, 'port', val)">
                       </el-input>
                     </template>
                   </div>
                 </li>
               </ul>
             </div>
           </transition>
         </div>
       </div>
     </div>
   </main>
  </div>
</template>

<script>
// 配置中心
export default {
  data() {
    return {
      // 列表loading
      tableLoading: false,
      btnLoading: false,
      // 列表数据
      tableData: [],
      // 已选中配置id
      checkList: [],
      // 获取当前用户的项目数据
      projectList: [],
      // 当前选择的项目id
      projectId: '',
      // 选择的配置id
      activeRoleId: 'module',
      // 项目配置信息
      configList: [
        {
          role_id: 'module',
          role_name: '模块配置'
        },
        {
          role_id: 'dataSource',
          role_name: '数据源配置'
        }
      ],
      // 数据源信息
      dataSource: {},
      // 数据源配置列表
      dataSourceList: []
    };
  },
  computed: {
    // 是否展示模块配置
    hasShowModule() {
      return this.activeRoleId === 'module';
    },
    // 设置数据源对应值
    setValue() {
      return (type, item) => {
        const key = item.data_source_name;
        const target = this.dataSource[key] || {};
        return target[type] || '';
      };
    },
    // 设置对应模块全选状态
    setIndeterminate() {
      return (data) => {
        const { checked, children = [] } = data;
        // 是否有选中的子节点
        const hasCheck = children.some(v => v.checked);
        // 是否有未选中的子节点
        const hasNoCheck = children.some(v => !v.checked);
        return !checked && hasCheck && hasNoCheck;
      };
    }
  },
  watch: {
    projectList(list) {
      if (Array.isArray(list) && list.length) {
        this.projectId = list[0].project_id;
      }
    },
    projectId(id, oldId) {
      if (id !== oldId) {
        this.getProjectModuleList();
        this.getDataSourceConfig();
      }
    }
  },
  async created() {
    await this.getModuleList();
    this.getProjectListByUser();
  },
  methods: {
    /**
     * 修改配置
     * @param checked {Boolean} 当前修改值
     * @param row {Object} 当前行数据
     */
    handleChange(checked, row) {
      const { module_id, deep, children = [] } = row;
      const index = this.checkList.findIndex(item => (
        item.module_id === module_id
      ));
      const hasParent = deep === 0;
      let newChildren = [];
      if (checked) { // 选中
        if (hasParent) { // 父节点选中
          this.checkList = this.checkList.filter(item => {
            return !children.some(val => (
              val.module_id === item.module_id
            ));
          });
          newChildren = children.map(val => {
            return {
              ...val,
              checked
            };
          });
        } else { // 子节点选中
          index === -1 && newChildren.push(row);
        }
        this.checkList.push(...newChildren);
      } else {
        if (hasParent) { // 父节点取消选中
          children.forEach(item => {
            const i = this.checkList.findIndex(v => (
              v.module_id === item.module_id
            ));
            i !== -1 && this.checkList.splice(i, 1);
          });
        } else {
          index !== -1 && this.checkList.splice(index, 1);
        }
      }
      this.updateTableData();
    },
    /**
     * 选择权限
     * @param item {Object} 当前选择权限数据
     */
    handleSelect(item) {
      this.activeRoleId = item.role_id;
    },
    /**
     * 数据源配置修改接口模式
     * @param item {Object} 当前对应修改项数据
     * @param key {String} 当前对应修改项标识
     * @param value {String} 修改值
     */
    handleDataChange(item, key, value) {
      const type = item.data_source_name;
      const target = this.dataSource[type];
      target && this.$set(this.dataSource, type, {
        ...target,
        [key]: value
      });
    },
    /**
     * 保存修改
     */
    async handleSave() {
      let success = true;
      this.btnLoading = true;
      if (this.hasShowModule) {
        success = await this.updateProjectModule();
      } else {
        success = await this.updateDataSourceConfig();
      }
      this.btnLoading = false;
      success && this.$message.success('保存成功');
    },
    /**
     * 更新所选项目的模块列表
     */
    async updateProjectModule() {
      if (!this.projectId) {
        this.$message.warning('请选择项目');
        return false;
      }
      const { success } = await this.$Model.updateProjectModule({
        project_id: this.projectId,
        module_id_list: this.checkList.map(item => item.module_id)
      });
      return success;
    },
    /**
     * 更新所选项目的数据源的数据
     */
    async updateDataSourceConfig() {
      const dataSource = Object.keys(this.dataSource).map(key => (
        this.dataSource[key]
      ));
      if (!dataSource.length) return false;
      const { success } = await this.$Model.updateDataSourceConfig({
        data: Object.keys(this.dataSource).map(key => this.dataSource[key])
      });
      return success;
    },
    /**
     * 设置全部模块列表的数据
     * @param list {Array} 列表初始数据
     */
    setTableData(list) {
      if (!Array.isArray(list)) return;
      // 将数据按页面进行归类
      const newList = list.reduce((pre, next) => {
        const currentItem = pre.find(item => (
          item.name === next.super_module_name
        ));
        if (currentItem) {
          currentItem.children.push({
            ...next,
            deep: 1,
            checked: false,
            name: next.module_name
          });
        } else {
          pre.push({
            uuid: `root-${next.uuid}`,
            deep: 0,
            checked: false,
            name: next.super_module_name,
            children: [{
              ...next,
              deep: 1,
              checked: false,
              name: next.module_name
            }]
          });
        }
        return pre;
      }, []);
      // 将没有配置项的页面过滤
      this.tableData = newList.filter(item => (
        item.children && item.children.length
      ));
    },
    /**
     * 更新列表数据
     */
    updateTableData() {
      const setCheck = (list) => {
        if (!Array.isArray(list) || !list.length) return [];
        return list.map(item => {
          const { children = [], deep, module_id } = item;
          let hasChecked = false; // 是否勾选
          if (deep === 0) {
            // 是否为全选状态
            hasChecked = children.every(val => {
              return this.checkList.some(v => (
                v.module_id === val.module_id
              ));
            });
          } else {
            hasChecked = this.checkList.some(v => (
              v.module_id === module_id
            ));
          }
          return {
            ...item,
            checked: hasChecked,
            children: setCheck(children)
          };
        });
      };
      this.tableData = setCheck(this.tableData);
    },
    /**
     * 设置接口模式下拉菜单
     */
    setDataSource() {
      if (!this.dataSourceList.length) return;
      this.dataSourceList.forEach(item => {
        this.$set(this.dataSource, item.data_source_name, {
          interface_type: item.interface_type || '',
          url: item.url || '',
          port: item.port || '',
          data_source_name: item.data_source_name || '',
          project_id: item.project_id
        });
      });
    },
    /**
     * 获取全部模块列表
     */
    async getModuleList() {
      this.tableLoading = true;
      const { success, data } = await this.$Model.getModuleList();
      this.tableLoading = false;
      success && this.setTableData(data.data);
    },
    /**
     * 获取所选项目的模块列表
     */
    async getProjectModuleList() {
      if (!this.projectId) return;
      this.tableLoading = true;
      const { success, data } = await this.$Model.getProjectModuleList({
        project_id: this.projectId
      });
      this.tableLoading = false;
      if (success) {
        this.checkList = data.data || [];
        this.updateTableData();
      }
    },
    /**
     * 获取当前用户的项目数据
     */
    async getProjectListByUser() {
      const { success, data } = await this.$Model.getProjectListByUser({
        user_id: this.$store.state.userInfo.userId
      });
      if (success) {
        this.projectList = data.data || [];
      }
    },
    /**
     * 获取所选项目的数据源配置
     */
    async getDataSourceConfig() {
      this.dataSourceList = [];
      if (!this.projectId) return;
      const { success, data } = await this.$Model.getDataSourceConfig({
        project_id: this.projectId
      });
      if (success && Array.isArray(data.data)) {
        // 获取所有对应的下拉菜单
        const requestList = data.data.map(item => {
          return this.getInterfaceType(item.data_source_name);
        });
        if (requestList.length) {
          const result = await Promise.all(requestList);
          // 将下拉菜单的值合并进数据源配置列表
          this.dataSourceList = data.data.map(val => {
            const currentItem = result.find(v => (
              v.data_source_name === val.data_source_name
            ));
            return {
              ...val,
              menuList: currentItem ? currentItem.menuList : []
            };
          });
        }
        this.setDataSource();
      }
    },
    /**
     * 获取所选数据源名称的接口模式下拉选项
     */
    async getInterfaceType(name) {
      if (!name) return;
      const params = {
        data_source_name: name,
      };
      const { success, data } = await this.$Model.getInterfaceType(params);
      return {
        ...params,
        menuList: success ? data.data : []
      };
    }
  }
};
</script>

<style scoped lang="scss">
  @import '../../assets/styles/table';

  .corp-config-page {
    width: 100%;
    height: 100%;
    main {
      width: 100%;
      height: 100%;
      padding: 20px 30px;
      background-color: $baseBg;
      border-width: 1px 0 0;
      border-style: solid;
      border-image: linear-gradient(to right, transparent 25%, #4f5073 35%, #6d719d 50%, #4f5073 65%, transparent 75%) 1 1;
      .content {
        padding: 20px;
        height: 100%;
        background-color: $mainBg;
        display: flex;
        justify-content: space-between;
        .config-container {
          width: 380px;
          height: 100%;
          .title-content {
            display: flex;
            justify-content: space-between;
            align-items: center;
            width: 100%;
            height: 30px;
            color: #fff;
            margin-bottom: 20px;
            .text {
              font-size: 20px;
            }
            .btns {
              i {
                margin-left: 10px;
                width: 25px;
                height: 25px;
                text-align: center;
                line-height: 25px;
                background-color: rgba(160, 164, 179, 0.4);
                border-radius: 5px;
                cursor: pointer;
                &:hover {
                  color: $lightBtnBg;
                }
              }
            }
          }
          .select-container {
            display: flex;
            align-items: center;
            margin-bottom: 15px;
            > span {
              color: $mainColor;
              margin-right: 15px;
              font-size: 14px;
            }
            .el-select {
              width: 300px;
              height: 40px;
              /deep/ input {
                background-color: $inputBg;
                border: none;
                color: #fff;
              }
            }
          }
          .role-list {
            width: 100%;
            max-height: 700px;
            overflow: auto;
            .role-item {
              position: relative;
              width: 360px;
              height: 40px;
              margin-bottom: 20px;
              border-radius: 10px 17px 0 10px;
              display: flex;
              align-items: center;
              justify-content: center;
              color: #fff;
              cursor: pointer;
              background: #31316d;
              &:after {
                content: '';
                position: absolute;
                right: -17px;
                top: 15px;
                width: 0;
                height: 0;
                border-width: 5px 20px;
                border-style: solid;
                border-color: #31316d #31316d transparent transparent;
                border-radius: 10px 6px 0 0;
                transform: rotate(70deg);
              }
              &:hover, &.active {
                background: $linearG;
                &:after {
                  border-color: #1f46dc #1f46dc transparent transparent;
                }
              }
              span {
                max-width: 200px;
                overflow: hidden;
                text-overflow: ellipsis;
              }
            }
          }
        }
        .table-container {
          height: 100%;
          margin-left: 50px;
          width: calc(100% - 430px);
          overflow: hidden;
          .btn-container {
            width: 100%;
            height: 90px;
            text-align: right;
            .success {
              width: 100px;
              height: 40px;
            }
          }
          .config-content {
            width: 100%;
            height: calc(100% - 90px);
            position: relative;
            overflow: hidden;
            /deep/ .el-table {
              position: absolute;
            }
          }
          .data-source-container {
            width: 100%;
            height: 100%;
            overflow: auto;
            color: #fff;
            position: absolute;
            .data-source-list {
              width: 100%;
              display: flex;
              flex-direction: column;
              justify-content: flex-start;
              .data-source-item {
                width: 100%;
                height: 150px;
                display: flex;
                flex-direction: column;
                justify-content: space-between;
                margin-bottom: 20px;
                padding: 10px 20px;
                border-radius: 10px;
                background: $inputBgRbga;
                .pattern {
                  display: flex;
                  justify-content:flex-start;
                  align-items: center;
                }
                label {
                  width: 110px;
                  display: inline-block;
                }
                .data-content {
                  display: flex;
                  justify-content: flex-start;
                  align-items: center;
                  .protocol {
                    width: 500px;
                    margin-right: 10px;
                  }
                  .port {
                    margin-left: 10px;
                    width: 100px;
                  }
                  .user {
                    width: 300px;
                  }
                  .password {
                    margin-left: 100px;
                  }
                }
              }
            }
          }
        }
      }
    }
    .module-fade-enter-active, .module-fade-leave-active {
      transition: all .8s;
      transform: translateX(0%);
      opacity: 1;
    }
    .module-fade-enter, .module-fade-leave-to {
      transform: translateX(100%);
      opacity: 0;
    }
  }
</style>
